package com.eregg.learn.netty.demo;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class NettyClient {

    public static final int MAX_RETRY = 5;

    public static void main(String[] args) throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();

        //group对应了我们IOClient.java中 main 函数起的线程
        NioEventLoopGroup group = new NioEventLoopGroup();

        bootstrap
                //1. 指定线程模型
                .group(group)
                //2. 指定IO模型，为NIO
                .channel(NioSocketChannel.class)
                //3. 指定处理逻辑
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel)  {
                        //socketChannel.pipeline().addLast(new StringEncoder());
                        //handler链
                        socketChannel.pipeline().addLast(new FirstClientHandler());
                    }
                });

        //4. 建立连接
        //connect1(bootstrap);

        //4. 建立连接，失败重连
        reConnect(bootstrap, "localhost", 8000, MAX_RETRY);
    }

    /**
     * 建立连接，并且发送消息给服务器端
     * @param bootstrap
     * @throws InterruptedException
     */
    private static void connect1(Bootstrap bootstrap) {
        ChannelFuture channelFuture = bootstrap.connect("localhost", 8000);
        //获取Channel
        sendMessage(channelFuture);
        return;
    }

    private static void sendMessage(ChannelFuture channelFuture) {
        try {
            Channel channel = channelFuture.channel();

            while (true){
                channel.writeAndFlush(new Date() + ": hello world!");
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 建立连接，失败重连
     * @param bootstrap
     * @param host
     * @param port
     * @param retry
     */
    private static void reConnect(Bootstrap bootstrap, String host, int port, int retry){
        ChannelFuture channelFuture = bootstrap.connect(host, port).addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    System.out.println("客户端连接服务器成功!");
                } else if (retry > 0) {
                    //第几次重连
                    int order = MAX_RETRY - retry + 1;
                    //本次重连的间隔
                    int delay = 1 << order;
                    System.out.println(String.format("%s 连接失败，第[%s]次重连，本次重连时间间隔[%s]s...", new Date(), order, delay));
                    bootstrap.config().group().schedule(() -> {
                        reConnect(bootstrap, host, port, retry - 1);
                    }, delay, TimeUnit.SECONDS);
                } else {
                    System.out.println("服务器没有响应，连接失败!");
                }
            }
        });

        sendMessage(channelFuture);
    }
}
